package com.woniuxy.amusementparkos.config;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.woniuxy.amusementparkos.realm.UserRealm;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;

/**
 *Shiro的基本配置 
 *包括Realm、安全管理器，过滤器，配置匹配器
 * @author fzw
 *
 */
@Configuration
public class ShiroConfiguration {
	private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
	/**
	 * 注入自定义的Realm
	 * @return 自定义登录验证的UserRealm
	 */
	@Bean
	public UserRealm myUserRealm() {
		UserRealm userRealm = new UserRealm();
		//将自定义Realm对应配置的配置匹配器
		userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		userRealm.setCacheManager(cacheManager());
		logger.info("====myRealm注册完毕=====");
		return userRealm;
	}
	
    /**
     * 注入安全管理器
     * @return SecurityManager
     */
    @Bean
    public SecurityManager securityManager() {
        // 将自定义 Realm 加进来
        SecurityManager securityManager = new DefaultWebSecurityManager(myUserRealm());
        return securityManager;
    }
    
    /**
     * 密码校验规则HashedCredentialsMatcher
     * 处理认证匹配处理器：如果自定义需要实现继承HashedCredentialsMatcher
     */
    @Bean("hashedCredentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //指定加密方式为MD5
        credentialsMatcher.setHashAlgorithmName("MD5");
        //加密次数
        credentialsMatcher.setHashIterations(1024);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }
    
    
	
    /**
     * 注入 Shiro 过滤器
     * @param securityManager 安全管理器
     * @return ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        // 定义 过滤工厂shiroFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        // 设置自定义的 securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 设置默认登录的 URL，身份认证失败会访问该 URL
        shiroFilterFactoryBean.setLoginUrl("/login.html");
        // 设置未授权界面，权限认证失败会访问该 URL
        shiroFilterFactoryBean.setUnauthorizedUrl("/login.html");
        // 设置成功之后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/backstage.html");
        //设置过滤器集合
        /**
         * key ：访问连接
         *      	支持通配符的形式
         * value：过滤器类型
         *      shiro常用过滤器
         *          anno ：匿名访问（表明此链接所有人可以访问）
         *          authc :认证后访问（表明此链接需登录认证成功之后可以访问）
         *
         */
        // LinkedHashMap 是有序的，进行顺序拦截器配置
        Map<String,String> filterChainMap = new LinkedHashMap<>();
        	// 登录 URL 放行
           filterChainMap.put("/login.html","anon");
           //登录Controller放行
           filterChainMap.put("/login*","anon");
           //静态资源放行
           filterChainMap.put("/build/**", "anon");
           filterChainMap.put("/plugin/**", "anon");
           filterChainMap.put("/src/**", "anon");
           //后台管理页面需要认证访问
           filterChainMap.put("/**","authc");	
//           filterChainMap.put("/**", "kickout,user");
           //自定义拦截器限制并发人数
//           LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();
           //限制同一帐号同时在线的个数
//           filtersMap.put("kickout", kickoutSessionControlFilter());
//           shiroFilterFactoryBean.setFilters(filtersMap);
           
        // 配置 logout 过滤器
        filterChainMap.put("/logout", "logout");

        // 设置 shiroFilterFactoryBean 的 FilterChainDefinitionMap
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }
    //配置themleaf支持权限标签的核心类
    //Dialect
    @Bean
    public ShiroDialect shiroDialect() {
    	return new ShiroDialect();
    }
    //配置授权缓存，使用内置的缓存
    @Bean
    public MemoryConstrainedCacheManager cacheManager() {
    	return new MemoryConstrainedCacheManager();
    }
    @Bean
    public	SessionManager sessionManager() {
    	DefaultSessionManager sessionManager = new DefaultSessionManager();
    	return sessionManager;
    }
    
    /**
     * 并发登录控制
     * @return
     */
//    @Bean
//    public KickoutSessionControlFilter kickoutSessionControlFilter(){
//        KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
//        //用于根据会话ID，获取会话进行踢出操作的；
//        kickoutSessionControlFilter.setSessionManager(sessionManager());
//        //使用cacheManager获取相应的cache来缓存用户登录的会话；用于保存用户—会话之间的关系的；
//        kickoutSessionControlFilter.setCacheManager(cacheManager());
//        //是否踢出后来登录的，默认是false；即后者登录的用户踢出前者登录的用户；
//        kickoutSessionControlFilter.setKickoutAfter(false);
//        //同一个用户最大的会话数，默认1；比如2的意思是同一个用户允许最多同时两个人登录；
//        kickoutSessionControlFilter.setMaxSession(1);
//        //被踢出后重定向到的地址；
//        kickoutSessionControlFilter.setKickoutUrl("/login?kickout=1");
//        return kickoutSessionControlFilter;
//    }
}
